package com.ndp.fb.walle.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;

import com.ndp.fb.util.StringUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ndp.ec.core.ProductManageService;
import com.ndp.ec.core.model.PlatformType;
import com.ndp.fb.config.ConfigCentre;
import com.ndp.fb.constant.CommonConstants;
import com.ndp.fb.enums.ErrorType;
import com.ndp.fb.enums.admarket.AdMarketStatus;
import com.ndp.fb.enums.productfeed.FeedWeCreatingStatus;
import com.ndp.fb.exception.CheckedException;
import com.ndp.fb.mongo.api.AdMarketTargetMongoService;
import com.ndp.fb.mongo.api.TargetingService;
import com.ndp.fb.mongo.model.autocreatead.AdMarketTarget;
import com.ndp.fb.mongo.model.autocreatead.AdMarketTargetHistory;
import com.ndp.fb.rdb.api.AdMarketTargetCountryRdbService;
import com.ndp.fb.rdb.api.AdPublishConditionRdbService;
import com.ndp.fb.rdb.api.DictionaryRdbService;
import com.ndp.fb.rdb.api.EcTemplateMaterielRdbService;
import com.ndp.fb.rdb.api.EcTrackingProfilesRdbService;
import com.ndp.fb.rdb.api.FeedRdbService;
import com.ndp.fb.rdb.api.ProductManageRdbService;
import com.ndp.fb.rdb.model.Adword;
import com.ndp.fb.rdb.model.EcTemplateMateriel;
import com.ndp.fb.rdb.model.EntrustAccount;
import com.ndp.fb.rdb.model.FeedWe;
import com.ndp.fb.rdb.model.GeoLocation;
import com.ndp.fb.rdb.model.User;
import com.ndp.fb.rdb.model.adpublishcondition.AdPublishCondition;
import com.ndp.fb.rdb.model.productmanage.ProductManage;
import com.ndp.fb.redis.api.RedisClient;
import com.ndp.fb.walle.business.AdMarketTargetService;
import com.ndp.fb.walle.business.AdwordService;
import com.ndp.fb.walle.model.vo.OutputResult;
import com.ndp.fb.walle.util.ResponseUtils;

/**
 * Created by Elvis on 2016/6/7.
 */
@RequestMapping("/admarket")
@RestController
public class AdMarketController {

    private final org.slf4j.Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private AdMarketTargetService adMarketTargetService;
    @Reference
    private FeedRdbService feedRdbService;
    @Reference
    private TargetingService targetingService;
    @Autowired
    private AdwordService adwordService;
    @Autowired
    private RedisClient redisClient;
    @Reference
    ProductManageService productManageService;
    @Reference
    EcTrackingProfilesRdbService ecTrackingProfilesRdbService;
    @Reference
    DictionaryRdbService dictionaryRdbService;
    @Reference
    private AdMarketTargetMongoService adMarketTargetMongoService;
    @Reference
    private AdPublishConditionRdbService adPublishConditionRdbService;
    @Reference
    private EcTemplateMaterielRdbService ecTemplateMaterielRdbService;
    @RequestMapping(value = "getAdMarketList")
    public JSONObject getAdMarketList(@RequestBody JSONObject param, HttpServletRequest request) throws Exception {
        logger.info("AdMarketController getAdMarketList() begin.");
        User user = (User) request.getSession().getAttribute("user");
        return adMarketTargetService.getAdMarketListWithStatsData(param, user.getTicket());
    }

    @RequestMapping(value = "getAdMarket")
    public ResponseEntity<String> getAdMarket(@RequestBody JSONObject param, HttpServletRequest request)
            throws Exception {
        logger.info("AdMarketController getAdMarket() begin.");
        ErrorType errorType = null;
        Map<String, Object> data = new HashMap<>();
        User user = (User) request.getSession().getAttribute("user");
        String strId = (String) param.get("id");
        AdMarketTarget adMarketTarget = adMarketTargetService.getAdMarketTarget(strId);
        if (adMarketTarget != null) {
            data.put("result", adMarketTarget);
        }
        OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, data);
        return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
    }

    @RequestMapping(value = "getAllAds")
    public JSONObject getAllAds(@RequestBody JSONObject param) throws Exception {
        logger.info("AdMarketController getAdMarketList() begin.");
        return adMarketTargetService.getAllAds(param);
    }

    @RequestMapping(value = "createAdMarket")
    @ResponseBody
    public ResponseEntity<String> createAdMarket(@RequestParam(value = "param", required = true) String param,
                                                 HttpServletRequest request) {
        logger.info("AdMarketController createAdMarket() begin.");
        ErrorType errorType = null;
        Map<String, Object> data = new HashMap<>();
        AdMarketTarget adMarketTarget = JSON.parseObject(param, AdMarketTarget.class);
        adMarketTarget.setId(UUID.randomUUID().toString());
        try {
            JSONObject object = new JSONObject();
            object.put("status", "creating");
            redisClient.set(CommonConstants.ADMARKETTARGET+adMarketTarget.getId(), object, 1, TimeUnit.HOURS.name());
            User user = (User) request.getSession().getAttribute("user");
            if(StringUtil.isNotEmpty(adMarketTarget.getTimeZone())){
                adMarketTarget.setTimeZone(adMarketTarget.getTimeZone().replaceAll(" ","")+":00") ;
            }
            adMarketTarget.setUserId(user.getTicket());
            adMarketTarget.setCreateTime(System.currentTimeMillis());
            adMarketTarget.setStatus(AdMarketStatus.CREATE.getCode());
            errorType = checkCreateMarketTarget(adMarketTarget, user);
            if(errorType==null){
                Long feedWeId = adMarketTarget.getFeedWeId();
                FeedWe feedWe = feedRdbService.findFeedWeById(feedWeId);
                adMarketTarget.setProductId(feedWe.getProductId());
                String adMtId = adMarketTargetService.save(adMarketTarget);
                if (adMtId != null) {
                    data.put("result", adMtId);
                }else{
                    errorType = ErrorType.AdMarketTarget_Create_ERROR;
                }
            }
        }catch (Exception e) {
            logger.error(e.getMessage(), e);
            errorType = ErrorType.AdMarketTarget_Create_ERROR;
        }
        OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, data);
        logger.info("AdMarketController createAdMarket() end.");
        return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
    }
    private ErrorType checkCreateMarketTarget(AdMarketTarget adMarketTarget,User user){
        Long feedWeId = adMarketTarget.getFeedWeId();
        FeedWe feedWe = feedRdbService.findFeedWeById(feedWeId);
        if(feedWe==null||FeedWeCreatingStatus.getStatus(feedWe.getOperateStatus())
                .getCode() < FeedWeCreatingStatus.SEND_FBFEED_OK.getCode()){
            return ErrorType.AdMarketTarget_Feed_Status_ERROR;
        }

        ProductManage productManage = productManageService.findByProductIdAndProductPlatform(feedWe.getProductId(), PlatformType.website.getPlatform());
        AdPublishCondition condition = adPublishConditionRdbService.findAdPublishCondition(productManage.getUserId(), productManage.getProdId(), PlatformType.website.getPlatform());
        if(productManage==null||condition==null){
            return ErrorType.AdMarketTarget_Publish_Condition_ERROR;
        }
        List<EntrustAccount> allowedAccounts = adPublishConditionRdbService.findAllowedAccounts(user.getTicket(), productManage.getProdId(), condition.getProdCfgId());
        if(CollectionUtils.isEmpty(allowedAccounts)){
            return ErrorType.AdMarketTarget_Adaccount_TimeZone_ERROR;
        }

        //检查是否有轮播创意类型的模板物料
        List<EcTemplateMateriel> materiels = ecTemplateMaterielRdbService.findByFeedIdAndCreativeType(adMarketTarget.getFeedWeId(), 11);
        if(CollectionUtils.isEmpty(materiels)){
            return ErrorType.AdMarketTarget_Materiel_ERROR;
        }

        List<String> pageTypes = adMarketTarget.getPageTypes();
        if(CollectionUtils.isEmpty(pageTypes)){
            return ErrorType.AdMarketTarget_PageType_ERROR;
        }
        if(!"gaRoi".equals(adMarketTarget.getOptimizeType())&&!"roi".equals(adMarketTarget.getOptimizeType())){
            return ErrorType.AdMarketTarget_OptimizeType_ERROR;
        }

        //获取账号时区
        Map<String, List<EntrustAccount>> actTimezoneMap = allowedAccounts.stream().collect(Collectors.groupingBy(EntrustAccount::getTimezone));
        List<EntrustAccount> entrustAccounts = null;
        for(Map.Entry<String, List<EntrustAccount>> entry:actTimezoneMap.entrySet()){
            //这里先用8时区的账号去试
            if(TimeZone.getTimeZone(ConfigCentre.getString("optimize_timezone","GMT+08:00")).getRawOffset()==TimeZone.getTimeZone(entry.getKey()).getRawOffset()){
                entrustAccounts = entry.getValue();
            }
        }
        if(CollectionUtils.isEmpty(entrustAccounts)){
            return ErrorType.AdMarketTarget_Adaccount_TimeZone_ERROR;
        }

        List<Long> profileIds = ecTrackingProfilesRdbService.findProfileIdsByProductIdAndTimeZone(productManage.getProdId(), 8);
        if(CollectionUtils.isEmpty(profileIds)){
            return ErrorType.AdMarketTarget_Ga_Profile_ERROR;
        }

        Adword adwords = adwordService.findRandomForRobot(user.getOrgId(), productManage.getProdId(), adMarketTarget.getLanguage());
        if (adwords==null) {
            return ErrorType.AdMarketTarget_AdWord_ERROR;
        }
        return null;
    }
    @RequestMapping(value = "updateAdMarket")
    @ResponseBody
    public ResponseEntity<String> updateAdMarket(@RequestParam(value = "param", required = true) String param,
                                                 HttpServletRequest request) {
        logger.info("AdMarketController updateAdMarket() begin.");
        ErrorType errorType = null;
        Map<String, Object> data = new HashMap<>();
        AdMarketTarget adMarketTarget = JSON.parseObject(param, AdMarketTarget.class);
        JSONObject object = new JSONObject();
        object.put("status", "optimizing");
        if(!redisClient.setNx(CommonConstants.ADMARKETTARGET+adMarketTarget.getId(), object, 1, TimeUnit.HOURS.name())){
            errorType = ErrorType.AdMarketTarget_Update_ERROR;
        }else{
            AdMarketTarget adMarketTargetOld = adMarketTargetService.getAdMarketTarget(adMarketTarget.getId());
            AdMarketTarget adMarketTargetNew = adMarketTargetOld;
            adMarketTargetNew.setTargetCountry(adMarketTarget.getTargetCountry());
            adMarketTargetNew.setFeedWeId(adMarketTarget.getFeedWeId());
            adMarketTargetNew.setDayBudget(adMarketTarget.getDayBudget());
            adMarketTargetNew.setTargetRoi(adMarketTarget.getTargetRoi());

            AdMarketTargetHistory histories = new AdMarketTargetHistory();
            histories.setTargetRoi(adMarketTargetNew.getTargetRoi());
            histories.setDayBudget(adMarketTargetNew.getDayBudget());
            histories.setCreateTime(System.currentTimeMillis());

            List<AdMarketTargetHistory> adMarketTargetHistories = adMarketTargetNew.getHistories();
            if (adMarketTargetHistories == null) {
                adMarketTargetHistories = new ArrayList<>();
            }
            adMarketTargetHistories.add(histories);
            adMarketTargetNew.setHistories(adMarketTargetHistories);
            adMarketTargetService.update(adMarketTargetNew);
        }
        OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, data);
        logger.info("AdMarketController updateAdMarket() end.");
        return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
    }

    @RequestMapping(value = "findAdMarket")
    @ResponseBody
    public JSONObject findAdMarket(@RequestBody JSONObject param, HttpServletRequest request) {
        logger.info("AdMarketController findAdMarket() begin.");
        User user = (User) request.getSession().getAttribute("user");
        return adMarketTargetService.findAdMarket(param.getString("id"), user);
    }

    @RequestMapping(value = "getAdMarketProductList")
    @ResponseBody
    public ResponseEntity<String> getMarketProductList(@RequestParam(value = "param", required = true) String param,
                                                       HttpServletRequest request) {
        logger.info("AdMarketController getMarketProductList() begin.");
        ErrorType errorType = null;
        Map<String, Object> data = new HashMap<>();
        User user = (User) request.getSession().getAttribute("user");

        List<ProductManage> productManageList = productManageService.findByOrgId(user.getOrgId());
        if (productManageList != null) {
            data.put("result", productManageList);
        }

        OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, data);
        logger.info("AdMarketController getMarketProductList() begin.");
        return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
    }

    @RequestMapping(value = "getAdMarketTargetCountry")
    @ResponseBody
    public ResponseEntity<String> getAdMarketTargetCountry(@RequestParam(value = "param", required = true) String param,
                                                           HttpServletRequest request) {
        logger.info("AdMarketController getMarketProductList() begin.");

        ErrorType errorType = null;
        Map<String, Object> data = new HashMap<>();
        List<GeoLocation> geolocations = targetingService.getAllCountry();
        data.put("result", geolocations);
        OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, data);

        logger.info("AdMarketController getMarketProductList() end.");
        return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
    }

    @RequestMapping(value = "getAdMarketFeed")
    @ResponseBody
    public ResponseEntity<String> getAdMarketFeed(@RequestParam(value = "param", required = true) String param,
                                                  HttpServletRequest request) {
        logger.info("AdMarketController getAdMarketFeed() begin.");
        ErrorType errorType = null;
        Map<String, Object> data = new HashMap<>();
        User user = (User) request.getSession().getAttribute("user");
        List<FeedWe> feedWeList = feedRdbService.queryFeedWeList(user.getOrgId());
        data.put("result", feedWeList);
        OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, data);
        logger.info("AdMarketController getAdMarketFeed() end.");
        return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
    }


    @RequestMapping(value = "optimizeAd")
    @ResponseBody
    public Map<String, Object> optimizeAd(@RequestBody JSONObject param) {
        String jobId = adMarketTargetService.optimizeAd(param);
        Map<String, Object> result = new HashMap<>();
        result.put("jobId", jobId);
        return result;
    }

    @RequestMapping(value = "pauseAdMarket")
    @ResponseBody
    public ResponseEntity<String> pauseAdMarket(@RequestParam(value = "param", required = true) String param) {
        ErrorType errorType = null;
        Map<String, Object> result = null;
        AdMarketTarget adMarketTarget = JSON.parseObject(param, AdMarketTarget.class);
        JSONObject object = new JSONObject();
        object.put("status", "stoping");
        if(!redisClient.setNx(CommonConstants.ADMARKETTARGET+adMarketTarget.getId(), object, 1, TimeUnit.HOURS.name())){
            errorType = ErrorType.AdMarketTarget_Update_ERROR;
        }else{
            adMarketTargetService.updateAdMarket(adMarketTarget.getId(), adMarketTarget.getStatus(),adMarketTarget.getPauseReason());
            result = new HashMap<>();
            result.put("ok", adMarketTarget.getId());
        }
        OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, result);
        return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
    }


    @RequestMapping(value = "getJobStatus")
    @ResponseBody
    public Map<String, Object> getJobStatus(@RequestBody JSONObject param) {
        return adMarketTargetService.getJobStatus(param);
    }
    @RequestMapping(value = "getLog")
    @ResponseBody
    public Object getLog(@RequestParam(value = "param", required = true) String param) {
        AdMarketTarget adMarketTarget = JSON.parseObject(param, AdMarketTarget.class);
        return adMarketTargetService.getLogs(adMarketTarget.getId());
    }


    public static void main(String[] args) {
        TimeZone timeZone = TimeZone.getTimeZone("GMT+09:30");
        System.out.println(timeZone.getRawOffset()%(3600*1000));


        TimeZone timeZone1 = TimeZone.getTimeZone("Asia/Shanghai");
        System.out.println(TimeZone.getTimeZone("GMT+08:00").hasSameRules(TimeZone.getTimeZone("Asia/Shanghai")));
    }
}
